﻿using System;
using System.Collections.Generic;
using Nancy;
using Nancy.Extensions;
using QQ2564874169.Core;
using QQ2564874169.Core.Caching;

namespace QQ2564874169.WebFx.Nancy.Web
{
    public class TempData : Dictionary<string, object>
    {
        public static Func<FxController, ICache> CreateContainer { get; set; }
        public static int DataTimeout { get; set; }
        private const string Cookie = "_tempdata_";
        private static ICache _data;
        private List<string> _isnew = new List<string>();

        static TempData()
        {
            DataTimeout = 30;
            CreateContainer = _ => new AppCache();
        }

        internal TempData(FxController module)
        {
            module.Before.AddItemToStartOfPipeline(Read);
            module.After.AddItemToEndOfPipeline(Write);
            _data = CreateContainer(module);
        }

        public new void Add(string key, object value)
        {
            if (_isnew.Contains(key) == false)
                _isnew.Add(key);
            base.Add(key, value);
        }

        public new object this[string key]
        {
            get { return ContainsKey(key) ? base[key] : null; }
            set
            {
                if (_isnew.Contains(key) == false)
                {
                    _isnew.Add(key);
                }
                if (ContainsKey(key))
                {
                    base[key] = value;
                }
                else
                {
                    base.Add(key, value);
                }
            }
        }

        private Response Read(NancyContext context)
        {
            if (context.Request.IsAjaxRequest())
                return null;
            if (context.Request.Cookies.ContainsKey(Cookie) == false)
                return null;
            var id = context.Request.Cookies[Cookie];
            if (string.IsNullOrEmpty(id)) return null;
            var items = _data.Get<List<DataItem>>(id);
            if (items != null)
            {
                foreach (var item in items)
                {
                    base.Add(item.Key, item.Value);
                }
            }
            return null;
        }

        private void Write(NancyContext context)
        {
            if (context.Request.IsAjaxRequest())
                return;
            if (_isnew.Count < 1 && context.Request.Cookies.ContainsKey(Cookie))
            {
                context.Response.WithCookie(Cookie, "", DateTime.Now.AddDays(-1));
                return;
            }
            var list = new List<DataItem>();
            foreach (var key in _isnew)
            {
                if (this[key] == null) continue;

                list.Add(new DataItem
                {
                    Key = key,
                    Value = this[key]
                });
            }
            if (list.Count < 1) return;
            var id = Guid.NewGuid().ToString();
            _data.Save(new CacheItem
            {
                Key = id,
                Value = list,
                AbsoluteExpiration = DataTimeout
            });
            context.Response.WithCookie(Cookie, id, DateTime.Now.AddSeconds(DataTimeout));
        }

        private class DataItem
        {
            public string Key { get; set; }
            public object Value { get; set; }
        }
    }
}
